package emptyinterface

import "fmt"

type EmptyInterface interface {
}

type Course struct {
	name  string
	price int
	url   string
}

func (c *Course) printInfo() string {
	return "课程信息"
}

type Printer interface {
	printInfo() string
}

func myPrint(i interface{}) {
	//什么类型都可以打印
	fmt.Printf("%v\n", i)
}

func myPrint2(x interface{}) {
	v, ok := x.(int)
	if ok {
		//x是int
		fmt.Printf("%d(%v), 整数 \n", v, x)
	} else {
		//什么类型都可以打印
		fmt.Printf("%v, 不是整数\n", x)
	}

}
func myPrint3(x interface{}) {
	//if v, ok := x.(int); ok {
	//	fmt.Printf("%d(整数) \n", v)
	//}
	//
	//if v, ok := x.(string); ok {
	//	fmt.Printf("%s(字符串) \n", v)
	//}

	switch v := x.(type) {
	case string:
		fmt.Printf("%s(字符串) \n", v)
	case int:
		fmt.Printf("%d(字符串) \n", v)
	default:
		fmt.Printf("%v(不确定什么类型) \n", v)
	}

}

func EmptyInterfaceLearn() {
	//空接口，类似于python或者java中的object
	//var i EmptyInterface{}
	var i interface{}
	i = Course{}
	fmt.Println(i)

	//空接口的第一个用途：可以把任意类型赋值给空接口变量
	i = 10
	fmt.Println(i)

	i = []string{"django", "scrapy"}
	fmt.Println(i)

	//空接口的第二个用途：函数参数传递
	myPrint(200)
	myPrint(i)

	//空接口的第三个用途：可以作为map的值
	var m = make(map[string]interface{})
	m["hello"] = 100
	m["nihao"] = "django"
	myPrint(m)

	teacherInfo := make(map[string]interface{})
	teacherInfo["name"] = "bobby"
	teacherInfo["age"] = 18
	teacherInfo["weight"] = 75.4
	teacherInfo["courses"] = []string{"django", "scrapy", "flask"}
	myPrint(teacherInfo)

	//接口的一个坑, struct实现接口的时候，不能使用指针作为接收者
	//c := Course{}
	//var c Printer = Course{} //上面这样func (c *Course) printInfo() string，报错
	//c.printInfo()

	//接口的一个规范：接口的名称一般以er结尾
}

func TypeAssertion() {
	var x interface{}
	x = 20
	//myPrint2(x)
	myPrint3(x)
	x = "nihao"
	//myPrint2(x)
	myPrint3(x)
	x = []string{"django", "scrapy"}
	myPrint3(x)
}
